﻿#region COPYRIGHT
//--------------------------------------------------------------------------------
// <copyright file="RayExtensions.cs" company="starLiGHT Entertainment Studios">
//    Copyright (c) 2007, 2008, 2009, 2010 
//       Roland Rosenkranz (Glatzemann@email.de)
// </copyright>
// <license>
//   This file is part of starLiGHT.Core.
//
//   starLiGHT.Core is free software: you can redistribute it and/or modify
//   it under the terms of the GNU Lesser General Public License as published by
//   the Free Software Foundation, either version 3 of the License, or
//   (at your option) any later version.
//
//   starLiGHT.Core is distributed in the hope that it will be useful,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   GNU Lesser General Public License for more details.
//
//   You should have received a copy of the GNU Lesser General Public License
//   along with starLiGHT.Core. If not, see http://www.gnu.org/licenses/.
//    
//   ADDITIONAL (commercial) LICENSES for starLiGHT.Core are available on request.
// </license>
// <version>
// **************[ starLiGHT.Engine SVN ]**********************
// * $Rev:: 620                   $:  Revision of last commit *
// * $Author:: unknown            $:  Author of last commit   *
// * $Date:: 2010-12-07 15:23:58 #$:  Date of last commit     *
// ************************************************************
// </version>
//--------------------------------------------------------------------------------
#endregion

namespace starLiGHT
{
    #region Using Statements
    using System;
    using System.Collections.Generic;
    using System.Text;
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Graphics;
    #endregion

    /// <summary>
    /// Extension methods for the Ray data type
    /// </summary>
    public static class RayExtensions
    {
#if !ZUNE
        private static VertexPositionColor[] verts = new VertexPositionColor[2];
        
        private static VertexPositionColor[] arrowVerts =
        {
            new VertexPositionColor(Vector3.Zero, Color.White),
            new VertexPositionColor(new Vector3(.5f, 0f, -.5f), Color.White),
            new VertexPositionColor(new Vector3(-.5f, 0f, -.5f), Color.White),
            new VertexPositionColor(new Vector3(0f, .5f, -.5f), Color.White),
            new VertexPositionColor(new Vector3(0f, -.5f, -.5f), Color.White),
        };
        
#if !MONO
        private static int[] arrowIndexs =
#else
		private static ushort[] arrowIndexs =
#endif
        {        
            0, 1,
            0, 2,
            0, 3,
            0, 4,
        };

        private static VertexDeclaration vertDecl;
        private static BasicEffect effect;

        /// <summary>
        /// Renders a Ray for debugging purposes.
        /// </summary>
        /// <param name="ray">The ray to render.</param>
        /// <param name="length">The distance along the ray to render.</param>
        /// <param name="graphicsDevice">The graphics device to use when rendering.</param>
        /// <param name="camera">The camera used to get the view and projection matrix.</param>
        /// <param name="color">The color to use drawing the ray.</param>
        public static void Render(this Ray ray, float length, GraphicsDevice graphicsDevice, ICamera3D camera, Color color)
        {
            if (effect == null)
            {
#if !XNA4
                vertDecl = new VertexDeclaration(graphicsDevice, VertexPositionColor.VertexElements);
                effect = new BasicEffect(graphicsDevice, null);
#else
                vertDecl = VertexPositionColor.VertexDeclaration;
                effect = new BasicEffect(graphicsDevice);
#endif                
                effect.VertexColorEnabled = false;
                effect.LightingEnabled = false;
            }

            verts[0] = new VertexPositionColor(ray.Position, Color.White);
            verts[1] = new VertexPositionColor(ray.Position + (ray.Direction * length), Color.White);

            effect.DiffuseColor = color.ToVector3();
            effect.Alpha = (float)color.A / 255f;

            effect.World = Matrix.Identity;
            effect.View = camera.View;
            effect.Projection = camera.Projection;

#if !XNA4
            graphicsDevice.VertexDeclaration = vertDecl;

            effect.Begin();
            foreach (EffectPass pass in effect.CurrentTechnique.Passes)
            {
                pass.Begin();

                graphicsDevice.DrawUserPrimitives(PrimitiveType.LineList, verts, 0, 1);

                effect.World = Matrix.Invert(Matrix.CreateLookAt(
                    verts[1].Position,
                    verts[0].Position,
                    (ray.Direction != Vector3.Up) ? Vector3.Up : Vector3.Left));
                effect.CommitChanges();

                graphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.LineList, arrowVerts, 0, 5, arrowIndexs, 0, 4);

                pass.End();
            }

            effect.End();
#else
            foreach (EffectPass pass in effect.CurrentTechnique.Passes)
            {
                pass.Apply();
                graphicsDevice.DrawUserPrimitives(PrimitiveType.LineList, verts, 0, 1);

                effect.World = Matrix.Invert(Matrix.CreateLookAt(
                    verts[1].Position,
                    verts[0].Position,
                    (ray.Direction != Vector3.Up) ? Vector3.Up : Vector3.Left));
                pass.Apply();

                graphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.LineList, arrowVerts, 0, 5, arrowIndexs, 0, 4);
            }
#endif
        }
#endif
    }
}
